#ifndef	__Hive_Accessor_H__
#define	__Hive_Accessor_H__

#include <vector>
#include <string>
#include "../nthive/nt_hive.h"

enum HKEY {
	HKEY_LOCAL_MACHINE = 0,
	HKEY_USERS,
	HKEY_CLASS_ROOT,
	HKEY_CURRENT_USER,
	HKEY_CURRENT_CONFIG,
	HKEY_INVALID_ROOT
};

class Windows_Information;

class Link_Relation
{
public:
	friend class Hive_Root;
	Link_Relation(const std::string & key, const std::string & target);
	Link_Relation() : is_shadow_(false) {}
	~Link_Relation();

	void	key_name(const std::string & name);
	const std::string & key_name() const;
	void	target(const std::string & name);
	const std::string & target() const;
	bool	shadow() const;
	void	shadow(bool flag);

private:
	std::string	key_name_;
	std::string	target_;
	bool	is_shadow_;
};

class Hive_Root
{
public:
	friend class	Hive_Accessor;
	typedef std::vector<Link_Relation> Link_Relations;

	Hive_Root() : root_type_(HKEY_INVALID_ROOT) {}
	~Hive_Root() {}
	void	root_key(const std::string & key);
	const std::string & root_key() const; // TODO: don't use std because this class was exported!
	HKEY	root_type() const;
	bool	add_relation(const Link_Relation & link);
	const Link_Relations & link_relations() const;

private:
	std::string & link_relation(const std::string & key_name);

	HKEY	root_type_;
	std::string	root_key_;
	Link_Relations	sub_keys_;
};

class	Hive_Accessor
{
public:
	typedef unsigned int DWORD;
	Hive_Accessor(const Windows_Information * win_info);
	~Hive_Accessor();

	int	reg_open(HKEY root, const char *path, int mode = HMODE_RW);
	int	reg_open(const char * root_name, const char *path, int mode = HMODE_RW);
	void	reg_close();
	bool	is_available() const;
	int	have_any_subkey(const char * path);
	int	add_key(const char *key_name);
	int	remove_key(const char * key_name);
	int	remove_allkeys(const char * key_name);
	int	delete_value(const char * val_name);
	int	add_value(const char * name, int type);
	int	value_modify(const char * name, int value);
	bool	get_value(const char * name, unsigned int &value);
	size_t	get_value(const char * name, wchar_t *& value);
	int	get_value(const char * name, void * buffer, size_t len, int & type) const;
	int	remove_allvalues(const char * key_name);
	int	subkey_foreach(const char * key_name, key_callback kcb, void * user_data);
	int	value_foreach(const char * key_name, val_callback vcb, void * user_data);
	const Hive_Root	& take_root(HKEY hkey) const;
	const Hive_Root	& take_root(const char * name) const;
	int	get_value_length(const char * val_path) const;
	int	get_value_type(const char * val_path) const;
	int	set_value(const char * name, void * buffer, size_t len, int type = -1);
	int	value_rename(const char * srcname, const char * dstname);
	int	key_export(const char *name, const char *filename, const char *prefix) const;
	bool	trace_to_parent_key();

	static const char * get_type_string(unsigned type);
private:
	Hive_Accessor();
	int	fill_linked_relation_array(const Windows_Information * win_info);
	int	get_current_control_set();
	bool	enter_key(const char *path);
	int	root_node_offset() const;
	bool	split_for_val_name_and_enter_key(const std::string & path, size_t & pos);
	char	*current_key_path();
	int	hive_backup();
	Hive_Root reg_roots_[HKEY_INVALID_ROOT + 1]; // 预留一个非法根键对象（可用于方法失败的返回值）
	hive *hive_;
	std::string prefix_;
	// 原始路径偏移，由于路径变换（如进入子键）会造成cdofs_值增加，此时如果想以原始路径为基点
	// 切换到另一条子键链下去，就必须有一个记录原始路径偏移的变量
	int	origin_offset_;
	int	cdofs_; // 路径变换偏移(change directory offset)，即改变注册表键路径后相对根的偏移量
	static bool s_is_current_controlset_maped;
	//static bool s_is_current_controlset_maped;
};
#endif
